package com.fowo.api.datainterface.service.impl.implCore;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.fowo.api.common.util.ContextHolder;
import com.fowo.api.datainterface.constants.DataTypeKind;
import com.fowo.api.datainterface.constants.RequestMethodKind;
import com.fowo.api.datainterface.model.DataContextModel;
import com.fowo.api.datainterface.service.serviceCore.BaseFromService;
import com.fowo.api.datainterface.service.serviceCore.BaseToService;
import com.fowo.api.datainterface.util.JScriptUtil;
import com.fowo.api.datainterface.util.JsonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.util.ArrayList;

/**
 * 数据接口 服务实现类
 */
@Service
@Slf4j
@DS("ds24")
@RequiredArgsConstructor
public class ServiceServiceImpl implements BaseFromService, BaseToService {
    @Override
    public DataTypeKind getType() {
        return DataTypeKind.Service;
    }

    private final JScriptUtil jScriptUtil;

    @Override
    public Object invokeFrom(DataContextModel.DatainterfaceFromModel from, JSONObject currentParamsMap, JSONObject currentHeadersMap) {
        String path = from.getInterfaceUrl();
        String statement = from.getQueryStatement();
        Assert.isTrue(StrUtil.isAllNotBlank(path, statement), "调用参数异常！");
        Object bean = ContextHolder.getApplicationContext().getBean(path);
        Assert.notNull(bean, "服务不存在！");
        Method method = ReflectUtil.getMethodByName(bean.getClass(), statement);
        Assert.notNull(method, "方法名错误！");
        if (!StrUtil.equalsIgnoreCase(RequestMethodKind.Invoke.getValue(), from.getRequestMethod())) {
            Assert.isTrue(false, "{} 目标接口 {} ，指定的查询类型 {} 错误 ！", StrUtil.concat(true, from.getTaskCode()), from.getEnCode(), from.getRequestMethod());
        }
        try {
            Object res = ReflectUtil.invoke(bean, method, currentParamsMap.values());
            return jScriptUtil.callJsFrom(from.getDataProcessing(), res == null ? new ArrayList<>() : res, null, null);
        } catch (Exception ex) {
            throw new RuntimeException(StrUtil.format("{} 执行服务来源接口 {} ，执行 {} 操作 {} 发生异常 ", StrUtil.concat(true, from.getTaskCode()), from.getEnCode(), StrUtil.concat(true, path, statement), StrUtil.subPre(JsonUtil.getObjectToString(currentParamsMap), 500), ExceptionUtil.getRootCauseMessage(ex)));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object invokeTo(DataContextModel.DatainterfaceToModel to, JSONObject currentParamsMap, JSONObject currentHeadersMap) {
        String path = to.getInterfaceUrl();
        String statement = to.getQueryStatement();
        Assert.isTrue(StrUtil.isAllNotBlank(path, statement), "调用参数异常！");
        Object bean = ContextHolder.getApplicationContext().getBean(path);
        Assert.notNull(bean, "服务不存在！");
        Method method = ReflectUtil.getMethodByName(bean.getClass(), statement);
        Assert.notNull(method, "方法名错误！");
        if (!StrUtil.equalsIgnoreCase(RequestMethodKind.Invoke.getValue(), to.getRequestMethod())) {
            Assert.isTrue(false, "{} 目标接口 {} ，指定的查询类型 {} 错误 ！", StrUtil.concat(true, to.getTaskCode()), to.getEnCode(), to.getRequestMethod());
        }
        try {
            currentParamsMap = jScriptUtil.callJsTo(to.getDataProcessing(), currentParamsMap, null, null);
            return ReflectUtil.invoke(bean, method, currentParamsMap.values());
        } catch (Exception ex) {
            throw new RuntimeException(StrUtil.format("{} 执行服务目标接口 {} ，执行 {} 操作 {} 发生异常 ", StrUtil.concat(true, to.getTaskCode()), to.getEnCode(), StrUtil.concat(true, path, statement), StrUtil.subPre(JsonUtil.getObjectToString(currentParamsMap), 500), ExceptionUtil.getRootCauseMessage(ex)));
        }
    }
}
